package com.sky.service.impl;

import com.sky.exception.BaseException;
import com.sky.mapper.DishMapper;
import com.sky.mapper.OrderMapper;
import com.sky.mapper.UserMapper;
import com.sky.service.ReportService;
import com.sky.service.WorkspaceService;
import com.sky.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author zzw
 * @date 2025/5/18
 * @description 数据统计服务实现
 */
@Slf4j
@Service
public class ReportServiceImpl implements ReportService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private DishMapper dishMapper;
    @Autowired
    private WorkspaceService workspaceService;


    /**
     * 用户统计
     *
     * @param begin 开始日期
     * @param end   结束日期
     * @return UserReportVO
     */
    @Override
    public UserReportVO getUserStatistics(LocalDate begin, LocalDate end) {
        // 执行查询
        List<Map<String, Object>> reportData = userMapper.getUserStatistics(begin, end);

        // 提取数据
        List<String> dateList = reportData.stream().map(data -> data.get("create_date").toString())
                                          .collect(Collectors.toList());

        List<String> newUserList = reportData.stream().map(data -> data.get("new_users").toString())
                                             .collect(Collectors.toList());

        List<String> totalUserList = reportData.stream().map(data -> data.get("total_users").toString())
                                               .collect(Collectors.toList());

        // 构建 UserReportVO 对象
        return UserReportVO.builder().dateList(String.join(",", dateList)).newUserList(String.join(",", newUserList))
                           .totalUserList(String.join(",", totalUserList)).build();
    }

    /**
     * 营业额统计
     *
     * @param begin 开始日期
     * @param end   结束日期
     * @return TurnoverReportVO
     */
    @Override
    public TurnoverReportVO getTurnoverStatistics(LocalDate begin, LocalDate end) {
        // 1.执行查询
        List<Map<String, Object>> turnoverReportData = orderMapper.getTurnoverStatistics(begin, end);

        // 2.提取结果
        List<String> dateList = turnoverReportData.stream().map(data -> data.get("date").toString())
                                                  .collect(Collectors.toList());
        List<String> turnoverList = turnoverReportData.stream().map(data -> data.get("turnover").toString())
                                                      .collect(Collectors.toList());

        // 3.构建 TurnoverReportVO 对象并返回
        return TurnoverReportVO.builder().dateList(String.join(",", dateList))
                               .turnoverList(String.join(",", turnoverList)).build();
    }

    /**
     * 获取销量排名top10
     *
     * @param begin 开始日期
     * @param end   结束日期
     * @return SalesTop10ReportVO
     */
    @Override
    public SalesTop10ReportVO getTop10(LocalDate begin, LocalDate end) {
        // 1.执行查询
        List<Map<String, Object>> top10Dish = dishMapper.getTop10(begin, end);

        // 2.提取结果
        List<String> nameList = top10Dish.stream().map(data -> data.get("name").toString())
                                         .collect(Collectors.toList());
        List<String> numberList = top10Dish.stream().map(data -> data.get("number").toString())
                                           .collect(Collectors.toList());

        // 3.构建 SalesTop10ReportVO 对象并返回
        return SalesTop10ReportVO.builder().nameList(String.join(",", nameList))
                                 .numberList(String.join(",", numberList)).build();
    }

    /**
     * 获取订单统计
     *
     * @param begin 开始日期
     * @param end   结束日期
     * @return OrderReportVO
     */
    @Override
    public OrderReportVO getReportOrderStatistics(LocalDate begin, LocalDate end) {
        // 1.执行查询
        List<Map<String, Object>> orderReportData = orderMapper.getReportOrderStatistics(begin, end);

        // 提取数据
        List<String> dateList = orderReportData.stream().map(data -> data.get("date").toString())
                                               .collect(Collectors.toList());

        List<String> orderCountList = orderReportData.stream().map(data -> data.get("orderCount").toString())
                                                     .collect(Collectors.toList());

        List<String> validOrderCountList = orderReportData.stream().map(data -> data.get("validOrderCount").toString())
                                                          .collect(Collectors.toList());

        // 计算汇总数据
        int totalOrderCount = orderReportData.stream()
                                             .mapToInt(data -> Integer.parseInt(data.get("orderCount").toString()))
                                             .sum();

        int validOrderCount = orderReportData.stream()
                                             .mapToInt(data -> Integer.parseInt(data.get("validOrderCount").toString()))
                                             .sum();

        double orderCompletionRate = totalOrderCount == 0 ? 0 : (double) validOrderCount / totalOrderCount;

        // 构建 OrderReportVO 对象
        return OrderReportVO.builder().dateList(String.join(",", dateList))
                            .orderCountList(String.join(",", orderCountList))
                            .validOrderCountList(String.join(",", validOrderCountList)).totalOrderCount(totalOrderCount)
                            .validOrderCount(validOrderCount).orderCompletionRate(orderCompletionRate).build();
    }

    /**
     * 导出近30天的运营数据报表
     *
     * @param response HttpServletResponse
     **/
    @Override
    public void exportBusinessData(HttpServletResponse response) {

        String SHEET_NAME = "Sheet1";

        LocalDate begin = LocalDate.now().minusDays(30);
        LocalDate end = LocalDate.now().minusDays(1);

        // 使用分层资源管理
        try (InputStream inputStream = getTemplateStream();
             XSSFWorkbook excel = new XSSFWorkbook(inputStream);
             ServletOutputStream out = response.getOutputStream()
        ) {

            XSSFSheet sheet = excel.getSheet(SHEET_NAME);
            fillHeader(sheet, begin, end);

            // 填充汇总数据
            BusinessDataVO summaryData = workspaceService.getBusinessData(
                    LocalDateTime.of(begin, LocalTime.MIN),
                    LocalDateTime.of(end, LocalTime.MAX)
                                                                         );
            fillSummary(sheet, summaryData);

            // 填充每日明细
            fillDailyDetails(sheet, begin);

            excel.write(out);
        }
        catch (IOException | NullPointerException e) {
            log.error("报表导出失败 [{} 至 {}]", begin, end, e);
            throw new BaseException("报表导出失败");
        }
    }

    private InputStream getTemplateStream() {
        String TEMPLATE_PATH = "template/运营数据报表模板.xlsx";

        InputStream stream = this.getClass().getClassLoader().getResourceAsStream(TEMPLATE_PATH);
        if (stream == null) {
            throw new BaseException("模板文件不存在: " + TEMPLATE_PATH);
        }
        return stream;
    }

    private void fillHeader(XSSFSheet sheet, LocalDate begin, LocalDate end) {
        DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        XSSFRow headerRow = sheet.getRow(1);
        String dateRange = begin.format(DATE_FORMATTER) + " 至 " + end.format(DATE_FORMATTER);
        headerRow.getCell(1).setCellValue(dateRange);
    }

    private void fillSummary(XSSFSheet sheet, BusinessDataVO data) {
        // 第3行数据
        XSSFRow row3 = sheet.getRow(3);
        safeSetCell(row3.getCell(2), data.getTurnover());
        safeSetCell(row3.getCell(4), data.getOrderCompletionRate());
        safeSetCell(row3.getCell(6), data.getNewUsers());

        // 第4行数据
        XSSFRow row4 = sheet.getRow(4);
        safeSetCell(row4.getCell(2), data.getValidOrderCount());
        safeSetCell(row4.getCell(4), data.getUnitPrice());
    }

    private void fillDailyDetails(XSSFSheet sheet, LocalDate begin) {
        DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        for (int i = 0; i < 30; i++) {
            LocalDate date = begin.plusDays(i);
            BusinessDataVO dailyData = workspaceService.getBusinessData(
                    LocalDateTime.of(date, LocalTime.MIN),
                    LocalDateTime.of(date, LocalTime.MAX)
                                                                       );

            XSSFRow row = sheet.getRow(7 + i);
            safeSetCell(row.getCell(1), date.format(DATE_FORMATTER));
            safeSetCell(row.getCell(2), dailyData.getTurnover());
            safeSetCell(row.getCell(3), dailyData.getValidOrderCount());
            safeSetCell(row.getCell(4), dailyData.getOrderCompletionRate());
            safeSetCell(row.getCell(5), dailyData.getUnitPrice());
            safeSetCell(row.getCell(6), dailyData.getNewUsers());
        }
    }

    private void safeSetCell(XSSFCell cell, Object value) {
        if (cell == null)
            return;

        if (value instanceof Number) {
            cell.setCellValue(((Number) value).doubleValue());
        } else if (value != null) {
            cell.setCellValue(value.toString());
        }
    }

}
